# 产物体积优化

产物体积的优化在生产环境中是非常重要的，因为它直接影响到了线上的用户体验。在这篇文档中，我们将介绍在 Rsbuild 中一些常见的产物体积优化方式。

## 减少重复依赖

在 Web 项目中，经常出现某些第三方依赖被打包了多个版本的现象。重复依赖会导致包体积变大、构建速度变慢。

### 检测重复依赖

你可以使用 [Rsdoctor](https://rsdoctor.rs) 来检测项目中是否存在重复依赖，Rsdoctor 会在构建过程中进行分析，找出所有重复打包的依赖包，并可视化展示出来：

![](https://assets.rspack.rs/rsbuild/assets/rsdoctor-duplicated-packages.png)

详见 [Rsdoctor - 重复依赖问题](https://rsdoctor.rs/zh/blog/topic/duplicate-pkg-problem)。

### 消除重复依赖

我们可以通过一些配置项和工具来检测或消除重复依赖。

- Rsbuild 提供了 [resolve.dedupe](/config/resolve/dedupe) 配置项，它允许你强制从项目根目录解析指定的包，从而移除重复包。

- 如果你在使用 `pnpm >= 7.26.0`，可以使用 pnpm 自带的 [pnpm dedupe](https://pnpm.io/cli/dedupe) 命令来升级和消除其中的重复依赖。

```bash
pnpm dedupe
```

- 如果你在使用 `pnpm < 7.26.0` 版本，可以使用 [pnpm-deduplicate](https://github.com/ocavue/pnpm-deduplicate) 来分析出所有的重复依赖，并通过升级依赖或声明 [pnpm overrides](https://pnpm.io/package_json#pnpmoverrides) 进行版本合并。

```bash
npx pnpm-deduplicate --list
```

- 如果你在使用 `yarn`，可以使用 [yarn-deduplicate](https://github.com/scinos/yarn-deduplicate) 来自动合并重复依赖：

```bash
npx yarn-deduplicate && yarn
```

## 使用更轻量的库

建议将项目中体积较大的三方库替换为更轻量的库，比如将 [moment](https://momentjs.com/) 替换为 [day.js](https://day.js.org/)。

如果你需要找出项目中体积较大的三方库，可以在执行构建时添加 `BUNDLE_ANALYZE=true` 环境变量：

```bash
BUNDLE_ANALYZE=true pnpm build
```

详见 [performance.bundleAnalyze](/config/performance/bundle-analyze) 配置项。

## 提升 Browserslist 范围

Rsbuild 会根据项目的 Browserslist 配置范围进行代码编译，并注入相应的 Polyfill。如果项目不需要兼容旧版浏览器，可以根据实际情况来提升 Browserslist 范围，从而减少在语法和 Polyfill 上的编译开销。

Rsbuild 默认的 Browserslist 配置为：

```js
['chrome >= 87', 'edge >= 88', 'firefox >= 78', 'safari >= 14'];
```

比如只兼容 Chrome 100 以上的浏览器，可以改成：

```js
['Chrome >= 100'];
```

:::tip
请阅读 [浏览器范围](/guide/advanced/browserslist) 章节来了解更多关于 Browserslist 的用法。
:::

## 按需引入 polyfill

如果当前项目的 [output.polyfill](/config/output/polyfill) 为 `'entry'`，在明确第三方依赖不需要额外 polyfill 的情况下，你可以将它设置为 `usage` 。

在 `usage` 模式下，Rsbuild 会分析源代码中使用的语法，按需注入所需的 polyfill 代码，从而减少 polyfill 的代码量。

```js
export default {
  output: {
    polyfill: 'usage',
  },
};
```

:::tip
请阅读 [浏览器兼容性](/guide/advanced/browser-compatibility) 章节来了解更多关于 polyfill 的用法。
:::

## 使用图片压缩

在一般的前端项目中，图片资源的体积往往是项目产物体积的大头，因此如果能尽可能精简图片的体积，那么将会对项目的打包产物体积起到明显的优化效果。你可以在 Rsbuild 中注册插件来启用图片压缩功能:

```ts title="rsbuild.config.ts"
import { pluginImageCompress } from '@rsbuild/plugin-image-compress';

export default {
  plugins: [pluginImageCompress()],
};
```

详见 [@rsbuild/plugin-image-compress](https://github.com/rspack-contrib/rsbuild-plugin-image-compress)。

## 代码拆包

良好的拆包策略对于提升应用的加载性能是十分重要的，可以充分利用浏览器的缓存机制，减少请求数量，加快页面加载速度。

在 Rsbuild 中内置了[多种拆包策略](/guide/optimization/code-splitting)，可以满足大部分应用的需求，你也可以根据自己的使用场景，自定义拆包配置。

比如将 node_modules 下的 `axios` 库拆分到 `axios.js` 中：

```js
export default {
  performance: {
    chunkSplit: {
      strategy: 'split-by-experience',
      forceSplitting: {
        axios: /node_modules[\\/]axios/,
      },
    },
  },
};
```
